package basic;

import java.util.Arrays;

public class Stats {
	/**
	 * mean
	 * 
	 * @param array
	 * @return
	 */
	public static double mean(double[] array) {
		double sum = 0;
		int size = 0;
		for (double score : array) {
			sum += score;
			size++;
		}
		double mean = sum / (size * 1D);
		return mean;
	}

	/**
	 * standard deviation (population/biased formula)
	 * 
	 * @param array
	 * @return
	 */
	public static double std(double[] array) {
		double sum = 0;
		int size = 0;
		double mean = mean(array);
		for (double element : array) {
			sum += Math.pow(element - mean, 2);
			size++;
		}
		double std = Math.sqrt(sum / (size * 1D));
		return std;
	}

	/**
	 * Returns the median of the given array. Input array does not have to be sorted.
	 * 
	 * @param array
	 * @return
	 */
	public static double median(double[] array) {
		double[] sortedArray = Arrays.copyOf(array, array.length);
		Arrays.sort(sortedArray);
		int middle = sortedArray.length / 2;
		if (sortedArray.length % 2 == 1) {
			return sortedArray[middle];
		} else {
			return (sortedArray[middle - 1] + sortedArray[middle]) / 2.0;
		}
	}

	/**
	 * Returns the sign function of the argument; zero if the argument is zero, 1.0 if the argument is greater than zero, -1.0 if the
	 * argument is less than zero.
	 * 
	 * @param d
	 *            double
	 * @return the sign of the input
	 */
	public static double sign(double d) {
		return Math.signum(d);
	}

	/**
	 * sqrt(a^2 + b^2) without under/overflow.
	 */
	public static double hypot(double a, double b) {
		double r;
		if (Math.abs(a) > Math.abs(b)) {
			r = b / a;
			r = Math.abs(a) * Math.sqrt(1 + r * r);
		} else if (b != 0) {
			r = a / b;
			r = Math.abs(b) * Math.sqrt(1 + r * r);
		} else {
			r = 0.0;
		}
		return r;
	}
}
